package com.pomelo.kill.listener;

import com.pomelo.kill.common.Constants;
import com.pomelo.kill.common.KillUtil;
import com.pomelo.kill.model.Goods;
import com.pomelo.kill.model.Order;
import com.pomelo.kill.service.GoodsService;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.redis.connection.Message;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.listener.KeyExpirationEventMessageListener;
import org.springframework.data.redis.listener.RedisMessageListenerContainer;
import org.springframework.stereotype.Component;

import javax.annotation.Resource;
import java.util.Map;
import java.util.Set;
import java.util.concurrent.TimeUnit;

@Component
@Slf4j
public class RedisKeyExpirationListener extends KeyExpirationEventMessageListener {

    @Resource
    private RedisTemplate<String, Object> redisTemplate;

    @Resource
    private GoodsService goodsService;

    public RedisKeyExpirationListener(RedisMessageListenerContainer listenerContainer) {
        super(listenerContainer);
    }

    /**
     * 针对redis数据失效进行处理
     *
     * @param message message must not be {@literal null}.
     * @param pattern pattern matching the channel (if specified) - can be {@literal null}.
     */
    @Override
    public void onMessage(Message message, byte[] pattern) {
        String k = message.toString();
        log.info("失效的key是：" + k);
        if (k.contains(Constants.REDIS_KILL_ORDER_USER)) {
            // 查询到失效的用户order订单
            Map<String, Order> map = (Map<String, Order>) redisTemplate.opsForValue().get(k);
            assert map != null;
            Set<String> keySet = map.keySet();
            for (String key : keySet) {
                // 将失效的商品信息返回到 redis 商品秒杀列表中
                key = key.substring(key.indexOf(Constants.REDIS_KILL_ORDER_USER));
                Goods goods = goodsService.selectByPrimaryKey(map.get(key).getGid());
                log.info("秒杀商品加入redis");
                redisTemplate.opsForValue().set(key, goods, KillUtil.getOffset(goods), TimeUnit.MILLISECONDS);
            }
        }
    }
}
